package com.liehu.user.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.liehu.user.dao.CustomerMapper;
import com.liehu.user.pojo.Customer;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import util.EncryptedDataUtils;
import util.IdWorker;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@Transactional //事务
public class CustomerService {
    @Autowired
    private CustomerMapper customerMapper;
    @Autowired
    private IdWorker idWorker;
    //Redis缓存
    @Autowired
    private RedisTemplate redisTemplate;
    //RabbitMQ消息队列
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private BCryptPasswordEncoder encoder; //随机加盐机密
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private EncryptedDataUtils encryptedDataUtils;//处理微信加密信息的工具类

    /**
     * 查询当前登录的用户信息
     */
    public Customer getUserInfo(){
        Claims claims_customer = (Claims) request.getAttribute("claims_customer");
        if(claims_customer == null ){
            return  null;
        }
        String customerId = claims_customer.getId();
        Customer customer = customerMapper.selectById(customerId);
        if(customer == null){
            return  null;
        }
        return  customer;
    }

    /**
     * 查询所有
     */
    public List<Customer> findAll(){
        return customerMapper.selectList(null);
    }
    /**
     * 根据id查询
     */
    public Customer findById(String id){
        return customerMapper.selectById(id);
    }
    /**
     * 根据电话号码查询
     */
    public Customer findByMobile(String mobile){
        return customerMapper.findByMobile(mobile);
    }

    /**
     * 插入
     */
    public void save(Customer customer){
        //先获取token
        Claims claims = (Claims) request.getAttribute("claims_customer");
        if(claims == null){
            throw new RuntimeException("权限不足！");
        }
        //给这条记录插入id
        customer.setId(idWorker.nextId()+"");
        //如果是有密码，则进行加盐机密处理。
        if(customer.getPassword()!=null && !"".equals(customer.getPassword())){
            //密码不为空，则进行加盐机密处理。
            customer.setPassword(encoder.encode(customer.getPassword()));
        }
        //插入
        customerMapper.insert(customer);
    }

    /**
     * 更新
     */
    public void update(Customer customer){
        //先获取token
        Claims claims = (Claims) request.getAttribute("claims_customer");
        if(claims == null){
            throw new RuntimeException("权限不足！");
        }
        //如果是修改密码，则进行加盐机密处理。
        if(customer.getPassword()!=null && !"".equals(customer.getPassword())){
            //密码不为空，则进行加盐机密处理。
            customer.setPassword(encoder.encode(customer.getPassword()));
        }
        customerMapper.updateById(customer);
    }
    /**
     * 根据id删除
     */
    public void deleteById(String id){
        //先获取token
        Claims claims = (Claims) request.getAttribute("claims_customer");
        if(claims == null){
            throw new RuntimeException("权限不足！");
        }
        customerMapper.deleteById(id);
    }
    /**
     * 分页查询
     */
    public Page<Customer> findByPage(Integer page,Integer size){
        Page<Customer> pageable = new Page<>(page,size);//创建分页对象
        return  customerMapper.selectPage(pageable, null);
    }
    /**
     * 条件分页查询
     */
    public Page<Customer> findByPage(Customer customer,Integer page,Integer size){
        Page<Customer> pageable = new Page<>(page,size);//创建分页对象
        QueryWrapper<Customer> wrapper = myWrapper(customer);//创建条件对象wrapper
        return  customerMapper.selectPage(pageable, wrapper);
    }

    /**
     * 内部处理条件
     * @param customer
     * @return
     */
    private QueryWrapper<Customer> myWrapper(Customer customer){
        QueryWrapper<Customer> wrapper = new QueryWrapper<>();
        //条件构造1
        if(customer.getNickName()!=null && !customer.getNickName().equals("")){
            wrapper.like("nick_name","%"+customer.getNickName()+"%");
        }
        //条件构造2
        if(customer.getEmail()!=null&&!customer.getEmail().equals("")){
            wrapper.eq("email",customer.getEmail());
        }
        //条件构造3
        if(customer.getId()!=null&&!customer.getId().equals("")){
            wrapper.eq("id",customer.getId());
        }
        //条件构造4
        if(customer.getMobile()!=null&&!customer.getMobile().equals("")){
            wrapper.eq("mobile",customer.getMobile());
        }
        //条件构造5
        if(customer.getStatus()!=null&&!customer.getStatus().equals("")){
            wrapper.eq("status",customer.getStatus());
        }
        return  wrapper;
    }

    /**
     * 发送短信
     * @param mobile
     */
    public void sendMsm(String mobile) {
        //1.生成6位数的随机短信
        String checkCode = RandomStringUtils.randomNumeric(6);
        //2.在redis中存取该验证码，有效时间为30分钟
        redisTemplate.opsForValue().set("checkCode"+mobile,checkCode,30L, TimeUnit.MINUTES);
        System.out.println(checkCode);
        //3.将手机号码和验证码推送给消息队列。
        Map<String,String> map = new HashMap<>(); //使用map封装参数。
        map.put("mobile",mobile);
        map.put("checkCode",checkCode);
        System.out.println(map);
        rabbitTemplate.convertAndSend("sms",map);
    }

    /**
     * 根据密码登录
     * @param mobile
     * @param password
     * @return
     */
    public Customer loginByPassword(String mobile, String password) {
        //根据电话号码查询
        Customer customer = customerMapper.findByMobile(mobile);
        //如果查询的结果 不为空并且密码正确，则返回查询到的结果。
        if(customer!=null && encoder.matches(password,customer.getPassword())){
            customer.setPassword(null);//将密码清空后再返回。
            return customer;
        }
        //否则直接返回Null;
        return null;
    }

    /**
     * 根据openId查询
     * @param openId
     * @return
     */
    public Customer findByOpenId(String openId) {
        return customerMapper.findByOpenId(openId);
    }

    /**
     * 解密，用于获取密码
     * @param encryptedData
     * @param iv
     * @return
     */
    public String encryptedMobile(String encryptedData, String iv) {
        //获取token
        Claims claims_customer = (Claims) request.getAttribute("claims_customer");
        if(claims_customer == null){
           throw new  RuntimeException("权限不足！");
        }
        String id = claims_customer.getId();//获取id
        String session_key = (String) redisTemplate.opsForValue().get("session_key" + id);//获取sessionKey
        if(session_key == null || session_key.equals("")){
            throw new  RuntimeException("Session_key已过期！");
        }
        //2.根据session_key、encryptedData、iv来解密获取手机号码
       JSONObject jsonNumber = (JSONObject) encryptedDataUtils.getPhoneNumber(encryptedData, session_key, iv);
        String mobile = jsonNumber.get("phoneNumber").toString();//获取的手机号码


        //3.将解密的手机号存入数据库
        Customer customer = new Customer();
        customer.setId(id);
        customer.setMobile(mobile);
        customerMapper.updateById(customer);

        return mobile;


    }

    public void updateByPassword(String password) {

        //先获取token
        Claims claims = (Claims) request.getAttribute("claims_customer");
        if(claims == null){
            throw new RuntimeException("权限不足！");
        }
        //获取token内的信息
        String id = claims.getId();
        //更新数据，对密码进行加盐机密处理
        customerMapper.updateByPassword(id,encoder.encode(password));
    }
}
